еӣ ж”¶еҲ°Googleзӣёе…ійҖҡзҹҘпјҢзҪ‘з«ҷе°ҶдјҡжӢ©жңҹе…ій—ӯгҖӮзӣёе…ійҖҡзҹҘеҶ…е®№

23 еә”з”Ёз•Ңйқўж•ҙеҗҲ

1. з•Ңйқўж•ҙеҗҲзҡ„йңҖжұӮеҲҶжһҗ

еҰӮдёӢжүҖзӨәпјҢеңЁеә”з”Ёзҡ„еә•йғЁж·»еҠ еҜјиҲӘж ҸпјҢиҝӣиЎҢз•Ңйқўй—ҙзҡ„еҲҮжҚўж“ҚдҪңгҖӮдёӢйқўд»Һж•°жҚ®е’Ңз•Ңйқўзҡ„и§’еәҰеҜ№иҜҘиҝӣиЎҢеҲҶжһҗпјҡ

———————————————————— ————————————————————
113.gif 114.gif

еҪ“еүҚз•ҢйқўдёӯйңҖиҰҒж·»еҠ зҡ„ж•°жҚ®жңү:

  • еә•йғЁж Ҹзҡ„ж–Үеӯ—гҖҒеӣҫж Үиө„жәҗеҲ—иЎЁ
  • еә•йғЁж Ҹзҡ„жҝҖжҙ»зҙўеј•

еңЁзӮ№еҮ»еә•йғЁж Ҹзҡ„жҢүй’®ж—¶пјҢйңҖиҰҒжӣҙж–°жҝҖжҙ»зҙўеј•пјҢе№¶иҝӣиЎҢз•Ңйқўзҡ„йҮҚж–°жһ„е»әгҖӮиҝҷйҮҢе®ҡд№үдёҖдёӘ MenuData зұ»пјҢз”ЁдәҺз»ҙжҠӨж Үзӯҫе’Ңеӣҫж Үж•°жҚ®пјҡ

class MenuData {
  // ж Үзӯҫ
  final String label;

  // еӣҫж Үж•°жҚ®
  final IconData icon;

  const MenuData({
    required this.label,
    required this.icon,
  });
}

еҜ№дәҺз•Ңйқўжһ„е»әйҖ»иҫ‘жқҘиҜҙпјҢиҝҷжҳҜдёҖдёӘдёҠдёӢз»“жһ„пјҢдёҠйқўжҳҜеҶ…е®№еҢәеҹҹпјҢдёӢйқўжҳҜеә•йғЁеҜјиҲӘж ҸгҖӮжүҖд»ҘпјҢеҸҜд»ҘйҖҡиҝҮ Column з»„д»¶дёҠдёӢжҺ’еҲ—пјҢе…¶дёӯеҶ…е®№еҢәеҹҹйҖҡиҝҮ Expanded з»„д»¶иҝӣиЎҢе»¶еұ•пјҢеҶ…е®№з»„д»¶ж №жҚ®жҝҖжҙ»зҡ„зҙўеј•еҖјжһ„е»әдёҚеҗҢзҡ„з•ҢйқўгҖӮ

image.png


2. д»Јз Ғе®һзҺ°пјҡ第дёҖзүҲ

Flutter дёӯжҸҗдҫӣдәҶ BottomNavigationBar з»„д»¶еҸҜд»Ҙеұ•зӨәеә•йғЁж ҸпјҢиҝҷйҮҢеҚ•зӢ¬е°ҒиЈ…дёҖдёӘ AppBottomBar з»„д»¶з”ЁдәҺз»ҙжҠӨеә•йғЁж Ҹзҡ„з•Ңйқўжһ„е»әйҖ»иҫ‘гҖӮе…¶дёӯйңҖиҰҒдј е…ҘжҝҖжҙ»зҙўеј•гҖҒзӮ№еҮ»еӣһи°ғгҖҒиҸңеҚ•ж•°жҚ®еҲ—иЎЁпјҡ

class AppBottomBar extends StatelessWidget {
  final int currentIndex;
  final List<MenuData> menus;
  final ValueChanged<int>? onItemTap;

  const AppBottomBar({
    Key? key,
    this.onItemTap,
    this.currentIndex = 0,
    required this.menus,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BottomNavigationBar(
      backgroundColor: Colors.white,
      onTap: onItemTap,
      currentIndex: currentIndex,
      elevation: 3,
      type: BottomNavigationBarType.fixed,
      iconSize: 22,
      selectedItemColor: Theme.of(context).primaryColor,
      selectedLabelStyle: const TextStyle(fontWeight: FontWeight.bold),
      showUnselectedLabels: true,
      showSelectedLabels: true,
      items: menus.map(_buildItemByMenuMeta).toList(),
    );
  }

  BottomNavigationBarItem _buildItemByMenuMeta(MenuData menu) {
    return BottomNavigationBarItem(
      label: menu.label,
      icon: Icon(menu.icon),
    );
  }
}

з„¶еҗҺе°ұжҳҜжһ„е»әж•ҙдҪ“з»“жһ„пјҢиҝҷйҮҢеҲӣе»әдёҖдёӘ AppNavigation з»„д»¶жқҘеӨ„зҗҶгҖӮз”ұдәҺжҝҖжҙ»зҙўеј•ж•°жҚ®йңҖиҰҒеңЁдәӨдә’ж—¶ж”№еҸҳпјҢе№¶йҮҚж–°жһ„е»әз•ҢйқўпјҢжүҖд»Ҙ AppNavigation з»§жүҝиҮӘ StatefulWidgetпјҢеңЁзҠ¶жҖҒзұ»дёӯеӨ„зҗҶз•Ңйқўжһ„е»әе’ҢзҠ¶жҖҒж•°жҚ®з»ҙжҠӨзҡ„йҖ»иҫ‘гҖӮ

class AppNavigation extends StatefulWidget {
  const AppNavigation({Key? key}) : super(key: key);

  @override
  State<AppNavigation> createState() => _AppNavigationState();
}

class _AppNavigationState extends State<AppNavigation> {
  int _index = 0;

  final List<MenuData> menus = const [
    MenuData(label: 'зҢңж•°еӯ—', icon: Icons.question_mark),
    MenuData(label: 'з”өеӯҗжңЁйұј', icon: Icons.my_library_music_outlined),
    MenuData(label: 'зҷҪжқҝз»ҳеҲ¶', icon: Icons.palette_outlined),
  ];

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Expanded( child: _buildContent(_index)),
        AppBottomBar(
          currentIndex: _index,
          onItemTap: _onChangePage,
          menus: menus,
        )
      ],
    );
  }

  void _onChangePage(int index) {
    setState(() {
      _index = index;
    });
  }

еҶ…е®№еҢәеҹҹзҡ„жһ„е»әдҪҝз”Ё _buildContent ж–№жі•пјҢж №жҚ®дёҚеҗҢзҡ„жҝҖжҙ»зҙўеј•пјҢиҝ”еӣһеҲӣе»әдёҚеҗҢзҡ„з•Ңйқўпјҡ

  • index = 0 ж—¶пјҢжһ„е»әзҢңж•°еӯ—з•Ңйқўпјӣ
  • index = 1 ж—¶пјҢжһ„е»әз”өеӯҗжңЁйұјз•Ңйқўпјӣ
  • index = 2 ж—¶пјҢжһ„е»әзҷҪжқҝз»ҳеҲ¶з•Ңйқўпјӣ
  Widget _buildContent(int index) {
    switch(index){
      case 0:
       return const GuessPage();
      case 1:
        return const MuyuPage();
      case 2:
        return const Paper();
      default:
        return const SizedBox.shrink();
    }
  }
}

еҲ°иҝҷйҮҢе°ұе®ҢжҲҗдәҶзӮ№еҮ»еә•йғЁеҜјиҲӘпјҢеҲҮжҚўз•Ңйқўзҡ„еҠҹиғҪпјҢеҪ“еүҚд»Јз ҒдҪҚзҪ®: navigation гҖӮ дҪҶиҝҷз§Қж–№ејҸеӨ„зҗҶдјҡжңүдёҖдәӣй—®йўҳпјҡдјҙйҡҸзқҖз•Ңйқўзҡ„ж¶ҲеӨұпјҢзҠ¶жҖҒзұ»дјҡиў«й”ҖжҜҒпјӣдёӢж¬ЎеҶҚеҲ°иҜҘз•Ңйқўж—¶дјҡйҮҚж–°еҲқе§ӢеҢ–зҠ¶жҖҒзұ»пјҢеҰӮдёӢжүҖзӨәпјҡ

еңЁз»ҳеҲ¶йқўжқҝз»ҳеҲ¶ еҲҮжҚўеҗҺпјҢзҠ¶жҖҒйҮҚзҪ®
115.gif 116.gif

3. зҠ¶жҖҒзұ»ж•°жҚ®зҡ„дҝқжҢҒ

жғіиҰҒйҒҝе…ҚжҜҸж¬ЎеҲҮжҚўйғҪдјҡйҮҚзҪ®зҠ¶жҖҒж•°жҚ®пјҢеӨ§дҪ“дёҠжңүдёүз§Қи§ЈеҶіж–№жЎҲпјҡ

  • 1.дҪҝз”Ё AutomaticKeepAliveClientMixin еҜ№зҠ¶жҖҒзұ»иҝӣиЎҢдҝқжҙ»пјҢиҝҷз§Қж–№жЎҲеҸӘиғҪз”ЁдәҺеҸҜж»‘еҠЁз»„д»¶дёӯгҖӮиҝҷйҮҢеҸҜд»ҘдҪҝз”Ё PageView з»„д»¶жқҘе®һзҺ°еҲҮйЎөе№¶дҝқжҙ»зҡ„ж•ҲжһңгҖӮ
  • 2.е°ҶзҠ¶жҖҒж•°жҚ®жҸҗеҚҮеҲ°дёҠеұӮпјҢжҜ”еҰӮе°ҶдёүдёӘз•Ңйқўзҡ„зҠ¶жҖҒж•°жҚ®йғҪдәӨз”ұ _AppNavigationState зҠ¶жҖҒзұ»з»ҙжҠӨгҖӮеҰӮжһңзӣҙжҺҘз”Ёиҝҷз§Қж–№ејҸпјҢеҫҲе®№жҳ“йҖ жҲҗдёҖдёӘи¶…зә§еӨ§зҡ„зұ»пјҢжқҘз»ҙжҠӨеҫҲеӨҡж•°жҚ®гҖӮе…¶е®һзҠ¶жҖҒз®ЎзҗҶе·Ҙе…·пјҢе°ұжҳҜеҹәдәҺиҝҷз§ҚжҖқи·ҜпјҢе°Ҷж•°жҚ®дәӨз”ұдёҠеұӮз»ҙжҠӨпјҢеҗҢж—¶жҸҗдҫӣдәҶеҲҶжЁЎеқ—еӨ„зҗҶж•°жҚ®зҡ„иғҪеҠӣгҖӮ
  • 3.дҝқжҢҒж•°жҚ®зҡ„жҢҒд№…жҖ§пјҢжҜ”еҰӮе°Ҷж•°жҚ®дҝқеӯҳеҲ°жң¬ең°ж–Үд»¶жҲ–ж•°жҚ®еә“пјҢжҜҸж¬ЎеҲқе§ӢеҢ–ж—¶иҝӣиЎҢеҠ иҪҪеӨҚзҺ°гҖӮиҝҷз§Қж–№ејҸеӨ„зҗҶиө·жқҘжҜ”иҫғйә»зғҰпјҢеҲқе§ӢеҢ–еҠ иҪҪж•°жҚ®д№ҹйңҖиҰҒдёҖзӮ№ж—¶й—ҙгҖӮдҪҶиҝҷз§Қж–№ејҸеңЁз•ҢйқўдёҚеҸҜи§Ғж—¶пјҢеҸҜд»ҘйҮҠж”ҫеҶ…еӯҳдёӯзҡ„ж•°жҚ®гҖӮ

иҝҷйҮҢдҪҝз”Ё ж–№ејҸ 1 жқҘеӨ„зҗҶжҳҜжңҖз®ҖеҚ•зҡ„гҖӮеңЁ _buildContent ж–№жі•дёӯиҝ”еӣһ PageView з»„д»¶пјҢе№¶е°ҶдёүдёӘеҶ…е®№з•ҢйқўдҪңдёә children е…ҘеҸӮпјҢйҖҡиҝҮ PageController жқҘжҺ§еҲ¶з•Ңйқўзҡ„еҲҮжҚўгҖӮжіЁж„ҸдёҖзӮ№пјҡе°Ҷ physics и®ҫзҪ®и®ҫзҪ®дёә NeverScrollableScrollPhysics еҸҜд»ҘзҰҒжӯў PageView зҡ„ж»‘еҠЁпјҢеҰӮжһңжғіиҰҒиҝҗиЎҢж»‘еҠЁеҲҮйЎөпјҢеҸҜд»ҘеҺ»йҷӨгҖӮ

---->[_AppNavigationState]----
final PageController _ctrl = PageController();

Widget _buildContent() {
  return PageView(
    physics: const NeverScrollableScrollPhysics(),
    controller: _ctrl,
    children: const [
       GuessPage(),
       MuyuPage(),
       Paper(),
    ],
  );
}

void _onChangePage(int index) {
  _ctrl.jumpToPage(index);
  setState(() {
    _index = index;
  });
}

еҸҰеӨ–еҰӮжһңжңҹжңӣжҹҗдёӘзҠ¶жҖҒзұ»дҝқжҙ»пјҢйңҖиҰҒи®©е…¶ж··е…Ҙ AutomaticKeepAliveClientMixin, е№¶иҰҶеҶҷ wantKeepAlive иҝ”еӣһ true гҖӮеҰӮдёӢжҳҜеҜ№з”»жқҝзҠ¶жҖҒзұ»зҡ„еӨ„зҗҶпјҢе…¶д»–дёӨдёӘеҗҢзҗҶпјҡ

image.png

еңЁз»ҳеҲ¶йқўжқҝз»ҳеҲ¶ еҲҮжҚўеҗҺпјҢзҠ¶жҖҒдҝқжҙ»
117.gif 118.gif

еҲ°иҝҷйҮҢпјҢе°ұе°Ҷд№ӢеүҚзҡ„дёүдёӘе°ҸжЎҲдҫӢпјҢйӣҶжҲҗеҲ°дәҶдёҖдёӘеә”з”ЁдёӯпјҢе№¶дё”еңЁеҲҮжҚўз•Ңйқўзҡ„иҝҮзЁӢдёӯпјҢеҸҜд»ҘдҝқжҢҒзҠ¶жҖҒж•°жҚ®дёҚиў«йҮҚзҪ®гҖӮеҪ“еүҚд»Јз ҒдҪҚзҪ® navigationгҖӮ

дёҠйқўеҸҜд»ҘдҝқиҜҒзЁӢеәҸиҝҗиЎҢжңҹй—ҙпјҢеҗ„з•ҢйқўзҠ¶жҖҒзұ»зҡ„дҝқжҙ»пјҢдҪҶжҳҜеҪ“еә”з”Ёе…ій—ӯд№ӢеҗҺпјҢеҶ…еӯҳдёӯзҡ„ж•°жҚ®дјҡиў«жё…з©әгҖӮеҶҚж¬Ўиҝӣе…Ҙеә”з”Ёж—¶иҝҳжҳҜж— жі•жҒўеӨҚеҲ°д№ӢеүҚзҡ„зҠ¶жҖҒпјҢжғіиҰҒи®°дҪҸз”ЁжҲ·зҡ„дҝЎжҒҜпјҢе°ұеҝ…йЎ»еҜ№ж•°жҚ®иҝӣиЎҢжҢҒд№…еҢ–зҡ„еӯҳеӮЁгҖӮжҜ”еҰӮеӯҳеӮЁдёәжң¬ең°ж–Үд»¶гҖҒж•°жҚ®еә“гҖҒзҪ‘з»ңж•°жҚ®зӯүпјҢдёӢдёҖзҜҮе°Ҷд»Ӣз»Қж•°жҚ®зҡ„жҢҒд№…еҢ–еӯҳеӮЁгҖӮ


4. дјҳеҢ–дёҖдәӣзјәйҷ·

еҰӮдёӢжүҖзӨәпјҢе·Ұдҫ§жҳҜ Column з»„д»¶дёҠдёӢжҺ’еҲ—пјҢеҪ“й”®зӣҳйЎ¶иө·д№ӢеҗҺпјҢеә•йғЁдјҡз•ҷеҮәдёҖеқ—з©әзҷҪпјҢй«ҳдёәеә•йғЁеҜјиҲӘй«ҳеәҰгҖӮжғіи§ЈеҶіиҝҷдёӘй—®йўҳпјҢдҪҝз”Ё Scaffold з»„д»¶еҚіеҸҜпјҢе®ғжңүдёҖдёӘ bottomNavigationBar зҡ„жҸ’ж§ҪпјҢдёҚдјҡиў«й”®зӣҳйЎ¶иө·гҖӮ

Column з»“жһ„ Scaffold з»“жһ„
image.png 42f13c95e59f1a9129353d2b3f22e37.jpg

иҝҷж—¶пјҢе°Ҷ _AppNavigationState зҡ„жһ„е»әж–№жі•ж”№дёәеҰӮдёӢд»Јз Ғпјҡ

 @override
 Widget build(BuildContext context) {
   return Scaffold(
     body: _buildContent(),
     bottomNavigationBar: AppBottomBar(
       currentIndex: _index,
       onItemTap: _onChangePage,
       menus: menus,
     ),
   );
 }

дёӢйқўд»Ҙ AppBar зҡ„дё»йўҳд»Ӣз»ҚдёҖдёӢ Flutter й»ҳи®Өй…ҚзҪ®зҡ„иғҪеҠӣгҖӮйЎ№зӣ®дёӯеёҢжңӣжүҖжңүзҡ„ AppBar йғҪжҳҜзҷҪиүІиғҢжҷҜгҖҒзҠ¶жҖҒзұ»йҖҸжҳҺгҖҒж Үйўҳеұ…дёӯгҖҒеӣҫж ҮйўңиүІгҖҒж–Үеӯ—йўңиүІдёәй»‘иүІгҖӮ

image.png

еҰӮжһңжҜҸж¬ЎдҪҝз”Ё AppBar з»„д»¶е°ұй…ҚзҪ®дёҖж¬ЎпјҢйӮЈд»Јз Ғд№ҰеҶҷе°ҶдјҡйқһеёёеӨҚжқӮгҖӮFlutter еңЁдё»йўҳж•°жҚ®зҡ„еҠҹиғҪпјҢеҸӘиҰҒжҢҮе®ҡдё»йўҳпјҢе…¶дёӢиҠӮзӮ№дёӯзҡ„еҜ№еә”з»„д»¶пјҢе°ұдјҡй»ҳи®ӨдҪҝз”Ёзҡ„й…ҚзҪ®ж•°жҚ®гҖӮеҰӮдёӢжүҖзӨәпјҢеңЁ MaterialApp зҡ„ theme е…ҘеҸӮдёӯеҸҜд»Ҙй…ҚзҪ®дё»йўҳж•°жҚ®пјҡ

image.png

иҝҷж ·пјҢд»ҘеүҚдҪҝз”Ё AppBar зҡ„ең°ж–№е°ұдёҚз”ЁеҶҚй…ҚзҪ®йӮЈд№ҲеӨҡдҝЎжҒҜдәҶгҖӮжҜ”еҰӮз”өеӯҗжңЁйұјз•Ңйқўзҡ„ AppBar е°ұеҸҜд»Ҙжё…зҲҪеӨҡдәҶпјҡ

image.png

иҝҷйҮҢеҸӘжҳҜжӢҝ AppBarTheme дёҫдёӘдҫӢеӯҗпјҢиҝҳжңүе…¶д»–еҫҲеӨҡзҡ„дё»йўҳеҸҜд»Ҙй…ҚзҪ®пјҢеӨ§е®¶еҸҜд»ҘеңЁд»ҘеҗҺж…ўж…ўдәҶи§ЈгҖӮ


5. жң¬з« е°Ҹз»“

жң¬з« жҲ‘们主иҰҒе°Ҷд№ӢеүҚзҡ„дёүдёӘе°ҸжЎҲдҫӢж•ҙеҗҲеҲ°дәҶдёҖдёӘйЎ№зӣ®дёӯпјҢйҖҡиҝҮеә•йғЁеҜјиҲӘж Ҹ + PageView е®һзҺ°з•Ңйқўй—ҙзҡ„еҲҮжҚўгҖӮеҸҰеӨ–д№ҹе°ұ State зҡ„зҠ¶жҖҒдҝқжҙ»иҝӣиЎҢдәҶз®ҖеҚ•ең°и®ӨиҜҶпјҢиҝҷйҮҢеҸӘжҳҜзЁӢеәҸиҝҗиЎҢжңҹй—ҙпјҢдҝқиҜҒеҗ„з•ҢйқўзҠ¶жҖҒзұ»зҡ„жҙ»жҖ§пјҢдҪҶжҳҜеҪ“еә”з”Ёе…ій—ӯд№ӢеҗҺпјҢеҶ…еӯҳдёӯзҡ„ж•°жҚ®дјҡиў«жё…з©әгҖӮеҶҚж¬Ўиҝӣе…Ҙеә”з”Ёж—¶иҝҳжҳҜж— жі•жҒўеӨҚеҲ°д№ӢеүҚзҡ„зҠ¶жҖҒгҖӮ

жғіиҰҒж°ёд№…и®°дҪҸз”ЁжҲ·зҡ„дҝЎжҒҜпјҢе°ұеҝ…йЎ»еҜ№ж•°жҚ®иҝӣиЎҢжҢҒд№…еҢ–зҡ„еӯҳеӮЁгҖӮжҜ”еҰӮеӯҳеӮЁдёәжң¬ең°ж–Үд»¶гҖҒж•°жҚ®еә“гҖҒзҪ‘з»ңж•°жҚ®зӯүпјҢеңЁзЁӢеәҸеҗҜеҠЁж—¶иҝӣиЎҢеҠ иҪҪпјҢжҒўеӨҚзҠ¶жҖҒж•°жҚ®гҖӮиҝҷжҳҜеә”з”ЁзЁӢеәҸйқһеёёйҮҚиҰҒзҡ„дёҖдёӘйғЁеҲҶпјҢдёӢдёҖзҜҮе°Ҷд»Ӣз»Қж•°жҚ®зҡ„жҢҒд№…еҢ–еӯҳеӮЁгҖӮ